<?php
namespace core;

use App\exceptions\ValidateException;

class Validate{
    protected  $rule = []; //规则列表
    protected  $data = []; //数据
    protected  $batch = false; //是否批量验证
    protected  $scene = [];
    protected  $nowScene = null;
    protected  $message = [];
    protected  $error = [];
    function __construct($rule=[])
    {
        if($rule){
            $this->rule($rule);
        }
    }

    /**
     * 批量错误
     * @param bool $batch
     */
    final public function batch($batch = true){
        $this->batch = $batch;
    }

    /**
     * 规则
     *  rule('name','require|max:25',['name.max'=>'姓名最大长度%s'])
     *  rule(['name'=>'require|max:25'])
     * @param $rule
     * @param string $regx
     * @param array $msg
     * @return Validate
     */
    final public function rule($rule,$regx='',$msg=[]){
        if(is_array($rule)){
            $this->rule = array_merge($this->rule, $rule);
            return $this;
        }
        $this->rule[$rule] = $regx;
        if($msg){
            $this->message = array_merge($this->message, $msg);
        }
        return $this;
    }

    /**
     * 校验数据
     * @param array $data 待校验数据
     * @return bool
     * @throws ValidateException
     */
    final public function check($data=[])
    {
        if(count($data)==0){
            throw  new ValidateException('缺少有效的验证数据');
        }
        $this->data = $data;
        $handelList = self::buildValidate();
        if(count($handelList)==0){
            throw  new ValidateException('缺少可用的验证方法');
        }
        return $this->doValidate($handelList);
    }
    final protected function doValidate($handelList){
        $this->error = []; //清空错误
        $res = true;
        foreach ($handelList as $dataKey => $funcList){
            foreach ($funcList as $funcKey=> $func){
                //验证失败
                if($func() === false){
                    $res = false;
                    if($this->batch){
                        break;
                    }else{
                        return false;
                    }
                };
            }
        }
        return $res;
    }
    /**
     * 构建验证规则
     * @throws ValidateException
     */
    final protected function buildValidate(){
        $ruleList = self::getValidateRule();
        if(count($ruleList)==0){
            throw  new ValidateException('缺少有效的验证规则');
        }
       return $this->formatHandel($ruleList);
    }

    /**
     * 消息封装简写
     * @param $flag
     * @param $key
     * @param $func
     * @param $param
     * @param string $msg
     * @return mixed
     */
   final protected function msgHandel($flag,$key,$func,$param,$msg=''){
       if(false === $flag){
           $this->formatErrorMsg($key,$func,$param,$msg);
       }
       return $flag;
    }
    /**
     * 格式化错误消息
     * @param $key
     * @param $func
     * @param $param
     * @param string $msg
     */
    final protected function formatErrorMsg($key,$func,$param,$msg=''){
        if(!is_array($param)){
            $param = [$param];
        }
        $errorMsg = $this->error[($key.'.'.$func)] ?? $msg;
        $this->error[] = sprintf($errorMsg,...$param);
    }
    //获取列表
    final static function getMethodsList(){
        return get_class_methods(static::class);
    }
    /**
     * 格式化 执行函数
     * @param $ruleList
     */
    final protected  function formatHandel($ruleList){
        $actHandelList = [];
        $funcList = self::getMethodsList();
        $class = $this;
        foreach ($ruleList as $dataKey => $ruleItem) {
            if(empty($ruleItem)) continue;
            $ruleFuncArr = $ruleItem;
            if(!is_array($ruleFuncArr)){
                $ruleFuncArr = explode('|',$ruleFuncArr);
            }
            foreach ($ruleFuncArr as $func){
                $funcInfoArr = explode(":",$func);
                //$param = explode(",",($funcInfoArr[1]??'')); //过滤参数
                $param = $funcInfoArr[1]??''; //过滤参数
                $func = $funcInfoArr[0];
                if(!in_array($func,$funcList)){
                    continue;
                }
                $actHandelList[$dataKey][$func] = function () use ($class,$dataKey,$func,$param){
                    return $class->$func($dataKey,$param);
                };
            }
        }
        return $actHandelList;
    }
    //获取待验证规则
    final protected function getValidateRule(){
        $validateList = $this->rule;
        if($this->nowScene && isset($this->scene[$this->nowScene])){
            $validateList = [];
            foreach ($this->scene[$this->nowScene] as $tempRule){
                if(isset($this->rule[$tempRule])){
                    $validateList[$tempRule] = $this->rule[$tempRule];
                }
            }
        }
        return $validateList;
    }

    /**
     * 场景
     */
   final public function scene($scene,$rule=[])
    {
        if(count($rule)){
            $this->scene[$scene] = $rule;
            return $this;
        }
        $this->nowScene = $scene;
        return $this;
    }
    /**
     * 消息
     */
    final public function message($key,$msg)
    {
        if(!empty($key) && !empty($msg)){
            $this->message[$key] = $msg;
        }
        return $this;
    }
    /**
     * 获取错误
     */
    final public function getError()
    {
        return $this->error;
    }

    /**
     * 验证函数：require 必填并且不能为空
     * @param $key
     * @return mixed
     */
    public function require($key){
        $flag = (in_array($key,$this->data) && !empty($this->data[$key]));
        return $this->msgHandel($flag,$key,__FUNCTION__,'',$key.'不能为空');
    }
    public function max($key,$len){

    }
    public function min($key,$len){
        var_dump('max',$key,$len);
    }
    public function between($key,$param){
        var_dump('between',$key,$param);
    }
}